package cli

import (
	"encoding/json"
	"flag"
	"fmt"
	"os"
)

func CLI(args []string) int {
	var app appEnv
	err := app.fromArgs(args)
	if err != nil {
		return 2
	}

	if err = app.run(); err != nil {
		fmt.Fprintf(os.Stderr, "Runtime error: %v\n", err)
		return 1
	}

	return 0
}

type appEnv struct {
	outputJSON bool
}

func (app *appEnv) fromArgs(args []string) error {
	fl := flag.NewFlagSet("cli", flag.ContinueOnError)

	outputType := fl.String(
		"o", "text", "Print output in format: text/json",
	)
	if err := fl.Parse(args); err != nil {
		return err
	}
	if *outputType != "text" && *outputType != "json" {
		fmt.Fprintf(os.Stderr, "got bad output type: %q\n", *outputType)
		fl.Usage()
		return flag.ErrHelp
	}
	app.outputJSON = *outputType == "json"
	return nil
}

func (app *appEnv) run() error {
	// business logic
	fmt.Println("Business logic")

	var resp APIResponse
	resp.Code = 200
	resp.Message = "OK"

	if app.outputJSON {
		return printJSON(resp)
	}

	return prettyPrint(resp)
}

type Output struct {
	Code    int    `json:"code"`
	Message string `json:"message"`
	Data    any    `json:"data"`
}

func printJSON(ar APIResponse) error {
	o := Output{
		Code:    200,
		Message: "OK",
		Data:    ar.GetData(),
	}
	b, err := json.MarshalIndent(&o, "", "  ")
	if err != nil {
		return err
	}
	fmt.Println(string(b))
	return nil
}

func prettyPrint(ar APIResponse) error {
	_, err := fmt.Printf(
		"Code: %d\nMessage: %s\nData: %v\n",
		ar.Code, ar.Message, ar.GetData(),
	)

	return err
}
